package middleware

import (
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"khao.fun/shizhan/common"
	"khao.fun/shizhan/model"
)

const (
	AccUnlogined     uint8 = 0
	AccLogined       uint8 = 1
	AccAdministrator uint8 = 2
	AccSuper         uint8 = 3
)

const (
	User          uint8 = 0
	Administrator uint8 = 1
	Super         uint8 = 2
)

//逻辑有点复杂，关联性较强，没事别乱改，顺序错了都会有问题
func AuthMiddleware(accessible_role uint8) gin.HandlerFunc {
	switch accessible_role {
	case AccUnlogined:
		return func(ctx *gin.Context) {
			getUserProfile(ctx)
			_, exist := ctx.Get("user")
			if exist {
				//设置identity方便其他地方需要查看身份
				checkIdentity(ctx)
				return
			}
			ctx.Set("identity", nil)
			ctx.Next()
		}
	case AccLogined:
		return func(ctx *gin.Context) {
			getUserProfile(ctx)
			_, exist := ctx.Get("user")
			if exist {
				//登录的人，未知身份，所以用这个来判断身份
				checkIdentity(ctx)
				ctx.Next()
				return
			}
			ctx.Abort()
		}
	case AccAdministrator:
		return func(ctx *gin.Context) {
			getUserProfile(ctx)
			user, ok := ctx.MustGet("user").(model.User_profile)
			if ok {
				if user.User_identity == Administrator {
					//身份已知
					ctx.Set("identity", Administrator)
					ctx.Next()
					return
				}
			}
			ctx.Abort()
		}
	case AccSuper:
		return func(ctx *gin.Context) {
			getUserProfile(ctx)
			user, ok := ctx.MustGet("user").(model.User_profile)
			if ok {
				if user.User_identity == Super {
					//身份已知
					ctx.Set("identity", Super)
					ctx.Next()
					return
				}
			}
			ctx.Abort()
		}
	default:
		return func(ctx *gin.Context) {
			ctx.Set("user", nil)
			ctx.Set("identity", nil)
			ctx.Next()
		}
	}
}

func getUserProfile(ctx *gin.Context) {
	tokenString := ctx.GetHeader("Authorization")
	if tokenString == "" || !strings.HasPrefix(tokenString, "Bearer") {
		ctx.JSON(http.StatusUnauthorized, gin.H{
			"code": 401,
			"msg":  "权限不够",
		})
		// ctx.Abort()
		return
	}
	tokenString = tokenString[7:]
	token, claims, err := common.ParseToken(tokenString)
	if err != nil || !token.Valid {
		ctx.JSON(http.StatusUnprocessableEntity, gin.H{
			"msg": "权限不足1",
			"error" : err,
		})
		// ctx.Abort()
		return
	}
	userId := claims.UserId
	DB := common.GetDB()
	var user model.User_profile
	DB.First(&user, userId)

	if user.User_id == 0 {
		ctx.JSON(http.StatusUnprocessableEntity, gin.H{
			"msg": "权限不足2",
		})
		// ctx.Abort()
		return
	}
	//Set global key
	ctx.Set("user", user)
}

func checkIdentity(ctx *gin.Context) {
	user, ok := ctx.MustGet("user").(model.User_profile)
	if ok {
		switch user.User_identity {
		case User:
			ctx.Set("identity", User)
		case Administrator:
			ctx.Set("identity", Administrator)
		case Super:
			ctx.Set("identity", Super)
		default:
			ctx.Set("identity", nil)
		}
	}
}
